package cnki.tpi.kbatis.config;

import cnki.tpi.kbatis.nodehandler.NodeHandler;
import cnki.tpi.kbatis.sqlnode.*;
import cnki.tpi.kbatis.sqlnode.iface.SqlNode;
import cnki.tpi.kbatis.sqlsource.DynamicSqlSource;
import cnki.tpi.kbatis.sqlsource.RawSqlSource;
import cnki.tpi.kbatis.sqlsource.iface.SqlSource;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName XMLScriptParser
 * @Description
 * @Author 小黄
 * @Date 2019/11/16 16:25
 * @Version 1.0
 */
public class XMLScriptParser {
    private boolean isDynamic = false;
    private Map<String, NodeHandler> map = new HashMap<String, NodeHandler>();

    public XMLScriptParser() {
        initMap();
    }

    private void initMap() {
        map.put("set", new SetNodeToHandler());
        map.put("where", new WhereNodeHandler());
        map.put("if", new ifNodeToHandler());
    }


    public SqlSource parseScriptNode(Element selectElement) {
        // 解析动态标签
        MixedSqlNode rootSqlNode = parseDynamicTags(selectElement);
        SqlSource sqlSource = null;
        if (isDynamic) {
            sqlSource = new DynamicSqlSource(rootSqlNode);
        } else {
            sqlSource = new RawSqlSource(rootSqlNode);
        }
        return sqlSource;
    }


    private MixedSqlNode parseDynamicTags(Element selectElement) {
        List<SqlNode> contents = new ArrayList<SqlNode>();
        int nodeCount = selectElement.nodeCount();
        for (int i = 0; i < nodeCount; i++) {
            Node node = selectElement.node(i);
            if (node instanceof Text) {
                String text = node.getText().trim();
                if (text == null || text.equals("")) {
                    continue;
                }
                text = " " + text;
                TextSqlNode textSqlNode = new TextSqlNode(text);
                if (textSqlNode.isDynamic()) {
                    isDynamic = true;
                    contents.add(textSqlNode);
                } else {
                    // 不包含 ${} 的 SQL
                    contents.add(new StaticTextSqlNode(text));
                }
            } else if (node instanceof Element) {
                Element nodeToHandler = (Element) node;
                String name = nodeToHandler.getName();
                NodeHandler nodeHandler = map.get(name);
                nodeHandler.nodeToHandler(nodeToHandler, contents);
                isDynamic = true;
            }
        }
        return new MixedSqlNode(contents);
    }

    /**
     * if标签handler
     */
    class ifNodeToHandler implements NodeHandler {

        @Override
        public void nodeToHandler(Element nodeToHandler, List<SqlNode> contents) {
            String textValue = nodeToHandler.attributeValue("test");
            MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandler);
            contents.add(new ifSqlNode(textValue, mixedSqlNode));
        }
    }

    /**
     * set标签handler
     */
    class SetNodeToHandler implements NodeHandler {
        public SetNodeToHandler() {
            // Prevent Synthetic Access
        }

        @Override
        public void nodeToHandler(Element nodeToHandler, List<SqlNode> contents) {
            MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandler);
            SetSqlNode set = new SetSqlNode(mixedSqlNode);
            contents.add(set);
        }
    }

    /**
     * where标签handler
     */
    class WhereNodeHandler implements NodeHandler {
        public WhereNodeHandler() {
            // Prevent Synthetic Access
        }

        @Override
        public void nodeToHandler(Element nodeToHandler, List<SqlNode> contents) {
            MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandler);
            WhereSqlNode where = new WhereSqlNode(mixedSqlNode);
            contents.add(where);
        }
    }
}
